home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / util / snopdos1 / part02 < prev   
Encoding:
Internet Message Format  |  1990-10-14  |  34.7 KB

  1. Path: abcfd20.larc.nasa.gov!amiga-request
  2. From: amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v90i283: SnoopDos 1.00 - Monitors calls to AmigaDOS functions, Part02/02
  4. Reply-To: Eddy Carroll <ECARROLL@vax1.tcd.ie>
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v90i283@abcfd20.larc.nasa.gov>
  7. References: <comp.sources.amiga:v90i282@abcfd20.larc.nasa.gov>
  8. Date: 14 Oct 90 19:07:11 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga
  12.  
  13. Submitted-by: Eddy Carroll <ECARROLL@vax1.tcd.ie>
  14. Posting-number: Volume 90, Issue 283
  15. Archive-name: util/snoopdos-1.0/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 2)."
  24. # Contents:  snoopdos.c
  25. # Wrapped by tadguy@abcfd20 on Sun Oct 14 15:07:02 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'snoopdos.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'snoopdos.c'\"
  29. else
  30. echo shar: Extracting \"'snoopdos.c'\" \(32250 characters\)
  31. sed "s/^X//" >'snoopdos.c' <<'END_OF_FILE'
  32. X/*
  33. X *        SNOOPDOS.C
  34. X *
  35. X *        (C) Copyright Eddy Carroll, May 1990. Freely distributable.
  36. X *
  37. X *        Snoopdos patches into dos.library and outputs a message to a
  38. X *        debugging window or file whenever a process calls certain DOS
  39. X *        functions.
  40. X *
  41. X *        Type snoopdos -h for a list of available options. See the
  42. X *        documentation for further details.
  43. X *
  44. X *        Compiles under Lattice C V5.04. I use flags: -cusq -j88i -ms -v
  45. X */
  46. X
  47. X#ifndef LATTICE_50
  48. X#include "system.h"
  49. X#endif
  50. X
  51. X/*
  52. X *        Assorted strings
  53. X */
  54. X#define TITLE \
  55. X"SnoopDos V1.0 (C) Copyright Eddy Carroll, Sept 1990. Freely distributable."
  56. X
  57. Xchar *HEADER =
  58. X"Process name          Func  Filename                                Mode Res."
  59. X"\r\n"
  60. X"------------          ----  --------                                ---- ----"
  61. X"\r\n";
  62. X
  63. X#define PORTNAME    "SnoopDos Port"
  64. X
  65. X#define DEFWINDOW    "CON:0/0/640/120/"
  66. X
  67. X/*
  68. X *        The following message array contains both colour and non-colour
  69. X *        versions of the various short message strings displayed.
  70. X */
  71. Xchar *msgs[][2] = {
  72. X/* Monochrome           Colour   */
  73. X/* ----------           ------   */
  74. X    "OLD ",                "OLD ",
  75. X    "NEW ",                "\033[33mNEW\033[0m ",
  76. X    "R/W ",                "\033[32mR/W\033[0m ",
  77. X    "??? ",                "??? ",
  78. X    "SHAR",                "SHAR",
  79. X    "EXCL",                "\033[33mEXCL\033[0m",
  80. X    "????",                "????",
  81. X    "Okay\r\n",            "Okay\r\n",
  82. X    "Fail\r\n",            "\033[33mFail\033[0m\r\n",
  83. X    ">",                "\033[33m>\033[0m",
  84. X    "> (Done)",            "> (Done)",
  85. X    "Warning: Missed",    "\033[33mWarning:\033[0m Missed",
  86. X    ">>>>\r\n",            ">>>>\r\n",
  87. X    "Open",                "Open",
  88. X    "Lock",                "\033[33mLock\033[0m",
  89. X    "Load",                "\033[32mLoad\033[0m",
  90. X    "Exec",                "\033[32mExec\033[0m",
  91. X    "CD  ",                "CD  ",
  92. X    "Del ",                "\033[33mDel\033[0m "
  93. X};
  94. X
  95. X#define TXT_OLD        msgs[ 0][colour]
  96. X#define TXT_NEW        msgs[ 1][colour]
  97. X#define TXT_R_W        msgs[ 2][colour]
  98. X#define TXT_QM3        msgs[ 3][colour]
  99. X#define TXT_SHAR    msgs[ 4][colour]
  100. X#define TXT_EXCL    msgs[ 5][colour]
  101. X#define TXT_QM4        msgs[ 6][colour]
  102. X#define TXT_OKAY    msgs[ 7][colour]
  103. X#define TXT_FAIL    msgs[ 8][colour]
  104. X#define TXT_POINT    msgs[ 9][colour]
  105. X#define TXT_DONE    msgs[10][colour]
  106. X#define TXT_WARN    msgs[11][colour]
  107. X#define TXT_NEST    msgs[12][colour]
  108. X#define TXT_OPEN    msgs[13][colour]
  109. X#define TXT_LOCK    msgs[14][colour]
  110. X#define TXT_LOAD    msgs[15][colour]
  111. X#define TXT_EXEC    msgs[16][colour]
  112. X#define TXT_CURDIR    msgs[17][colour]
  113. X#define TXT_DELETE    msgs[18][colour]
  114. X
  115. X#define POINT(x)    ((x) ? TXT_POINT : " ")
  116. X
  117. X/*
  118. X *        Now some standard system-type macros
  119. X */
  120. X#define reg_d0    register __d0
  121. X#define reg_d1    register __d1
  122. X#define reg_d2    register __d2
  123. X#define reg_d3    register __d3
  124. X#define reg_a0    register __a0
  125. X
  126. X#define BTOC(x)    (void *)(((ULONG)x) << 2)
  127. X
  128. X#define D_S(name, type) char c_##name[sizeof(type)+3];\
  129. X                        type *name = (type *)((long)(c_##name+3) & ~3)
  130. X
  131. Xextern __asm BPTR CallOpen(reg_d1 UBYTE *, reg_d2 int);
  132. Xextern __asm BPTR CallLock(reg_d1 UBYTE *, reg_d2 int);
  133. Xextern __asm BPTR CallLoadSeg(reg_d1 UBYTE *);
  134. Xextern __asm LONG CallExecute(reg_d1 UBYTE *, reg_d2 BPTR, reg_d3 BPTR);
  135. Xextern __asm BPTR CallCurrentDir(reg_d1 BPTR);
  136. Xextern __asm LONG CallDeleteFile(reg_d1 UBYTE *);
  137. X
  138. X/*
  139. X *        Structure used to pass messages back and fro
  140. X */
  141. Xtypedef struct {
  142. X    struct Message msg;            /* Standard message header    */
  143. X    struct Process *process;    /* Sending process id        */
  144. X    int msgtype;                /* Message type, see below    */
  145. X    int  data1;                    /* Data field 1                */ 
  146. X    void *data2;                /* Data field 2                */
  147. X} MYMSG;
  148. X
  149. X/*
  150. X *        Now the various settings that can be set to affect the monitoring
  151. X */
  152. Xtypedef struct {
  153. X    int set_doopen;                /* If true, monitor Open()            */
  154. X    int    set_dolock;                /* If true, monitor Lock()            */
  155. X    int set_doloadseg;            /* If true, monitor LoadSeg()        */
  156. X    int set_doexecute;            /* If true, monitor Execute()        */
  157. X    int set_docurdir;            /* If true, monitor CurrentDir()    */
  158. X    int set_dodelete;            /* If true, monitor DeleteFile()    */
  159. X    int    set_showfullpath;        /* If true, display full paths        */
  160. X    int set_sleepwait;            /* If true, sleep if necessary        */
  161. X    int set_snoopactive;        /* If true, monitoring is active    */
  162. X    int set_colour;                /* If true, use ANSI colour codes    */
  163. X} SETTINGS;
  164. X
  165. X/*
  166. X *        Default settings
  167. X */
  168. XSETTINGS settings = { 1, 0, 1, 1, 1, 1, 0, 0, 1, 1 };
  169. X
  170. X/*
  171. X *        These defines allow the various settings to be accessed as
  172. X *        normal variables rather than structure members; this is purely
  173. X *        for convenience.
  174. X */
  175. X#define doopen            settings.set_doopen
  176. X#define dolock            settings.set_dolock
  177. X#define doloadseg        settings.set_doloadseg
  178. X#define doexecute        settings.set_doexecute
  179. X#define docurdir        settings.set_docurdir
  180. X#define dodelete        settings.set_dodelete
  181. X#define showfullpath    settings.set_showfullpath
  182. X#define sleepwait        settings.set_sleepwait
  183. X#define snoopactive        settings.set_snoopactive
  184. X#define colour            settings.set_colour
  185. X
  186. X/*
  187. X *        Now the various message types that can be sent
  188. X */
  189. Xtypedef enum {
  190. X    MSG_QUIT,            /* Quit                     */
  191. X    MSG_GETOPTIONS,        /* Read options                */
  192. X    MSG_SETOPTIONS,        /* Update options            */
  193. X    MSG_OPEN,            /* Open file                */
  194. X    MSG_OPEN_DONE,        /* Open file completed        */
  195. X    MSG_LOCK,            /* Lock file                */
  196. X    MSG_LOCK_DONE,        /* Lock file completed        */
  197. X    MSG_LOADSEG,        /* LoadSeg file                */
  198. X    MSG_LOADSEG_DONE,    /* LoadSeg file completed    */
  199. X    MSG_EXECUTE,        /* Execute command            */
  200. X    MSG_CURDIR,            /* CurrentDir                */
  201. X    MSG_DELETE,            /* DeleteFile                */
  202. X    MSG_DELETE_DONE,    /* DeleteFile completed        */
  203. X} MSGTYPES;
  204. X
  205. Xstruct SignalSemaphore sem[1];
  206. Xstruct MsgPort   *myport;        /* Pointer to background SnoopDos msg port    */
  207. Xstruct MsgPort   *inport;        /* Pointer to our own message port            */
  208. Xstruct Task      *snooptask;    /* Pointer to our own task                    */
  209. XBPTR debugwin;                    /* Output file or window                    */
  210. XBPTR stderr;                    /* Standard CLI console                        */
  211. Xint  extfile;                    /* True if output directed to external file    */
  212. Xchar extfilename[100];            /* Name of window/file to open if specified    */
  213. Xchar outbuf[800];                /* Output buffer used by myprintf() etc.    */
  214. X
  215. Xint missed_open_sig;            /* Signal to indicate Open() missed            */
  216. Xint missed_lock_sig;            /* Signal to indicate Lock() missed            */
  217. Xint missed_loadseg_sig;            /* Signal to indicate LoadSeg() missed        */
  218. Xint missed_execute_sig;            /* Signal to indicate Execute() missed        */
  219. Xint missed_curdir_sig;            /* Signal to indicate CurrentDir() missed    */
  220. Xint missed_delete_sig;            /* Signal to indicate DeleteFile() missed    */
  221. Xint portsig;                    /* Signal used by our public port            */
  222. X
  223. X/**************************** Start of Functions ****************************/
  224. X
  225. X/*
  226. X *        cleanup()
  227. X *        ---------
  228. X *        Cleans up all active resources and exits. If err is -1, then
  229. X *        returns instead of exiting.
  230. X */
  231. Xvoid cleanup(int err)
  232. X{
  233. X    static int called = 0;
  234. X
  235. X    if (called++)        /* Make sure not called twice by accident */
  236. X        return;
  237. X
  238. X    if (inport)
  239. X        DeletePort(inport);
  240. X
  241. X    if (debugwin)
  242. X        Close(debugwin);
  243. X
  244. X    if (stderr)
  245. X        Close(stderr);
  246. X
  247. X    if (err != -1)
  248. X        exit(err);
  249. X}
  250. X
  251. X/*
  252. X *        myprintf(), myfprintf()
  253. X *        -----------------------
  254. X *        Two low cost alternatives to printf that go directly to AmigaDOS
  255. X *        Note we deliberately use the pre-ANSI declaration, to avoid Lattice
  256. X *        kicking up a fuss about the wrong number of parameters.
  257. X */
  258. Xvoid myprintf(format, p1, p2, p3, p4, p5, p6)
  259. XUBYTE *format;
  260. XULONG p1, p2, p3, p4, p5, p6;
  261. X{
  262. X    sprintf(outbuf, format, p1, p2, p3, p4, p5, p6);
  263. X    Write(Output(), outbuf, strlen(outbuf));
  264. X}
  265. X
  266. Xvoid myfprintf(file, format, p1, p2, p3, p4, p5, p6)
  267. XBPTR file;
  268. Xchar *format;
  269. XULONG p1, p2, p3, p4, p5, p6;
  270. X{
  271. X    sprintf(outbuf, format, p1, p2, p3, p4, p5, p6);
  272. X    Write(file, outbuf, strlen(outbuf));
  273. X}
  274. X
  275. X#define printf  myprintf
  276. X#define fprintf myfprintf
  277. X
  278. X/*
  279. X *        sendmsg()
  280. X *        ---------
  281. X *        Sends a message to myport, and waits for a reply to arrive.
  282. X *        A message type and some message data are all that need be provided
  283. X *        by the caller; the callee will provide the rest. Doesn't return
  284. X *        until a reply has been received.
  285. X */
  286. Xvoid sendmsg(int type, int data1, void *data2)
  287. X{
  288. X    MYMSG msg;
  289. X    struct Process *me = (struct Process *)FindTask(0);
  290. X    struct MsgPort *replyport = &me->pr_MsgPort;
  291. X
  292. X    msg.msg.mn_Node.ln_Type = NT_MESSAGE;
  293. X    msg.msg.mn_Length       = sizeof(MYMSG);
  294. X    msg.msg.mn_ReplyPort    = replyport;
  295. X    msg.process                = me;
  296. X    msg.msgtype             = type;
  297. X    msg.data1               = data1;
  298. X    msg.data2               = data2;
  299. X
  300. X    PutMsg(myport, &msg);
  301. X    WaitPort(replyport);
  302. X    GetMsg(replyport);
  303. X}
  304. X
  305. X
  306. X/*
  307. X *        getlockpath()
  308. X *        -------------
  309. X *        Returns a pointer to a string containing the full path for the
  310. X *        specified lock. You must copy the string before calling this
  311. X *        routine again.
  312. X */
  313. Xchar *getlockpath(BPTR lock)
  314. X{
  315. X    struct Process *p = (struct Process *)FindTask(0L);
  316. X    APTR oldwin = p->pr_WindowPtr;
  317. X    static char path[300];
  318. X    int pos = 299;
  319. X    BPTR mylock;
  320. X    char *name;
  321. X    D_S(fib, struct FileInfoBlock);
  322. X    int err = 0;
  323. X
  324. X    p->pr_WindowPtr = (APTR)-1;    /* Disable error requesters */
  325. X    mylock = DupLock(lock);
  326. X
  327. X    path[pos] = '\0';
  328. X
  329. X    do {
  330. X        int len;
  331. X        BPTR newlock;
  332. X
  333. X        if (!Examine(mylock, fib))
  334. X            err++;
  335. X        name = fib->fib_FileName;
  336. X        if (*name == '\0')
  337. X            name = "RAM";        /* Workaround for old RAM: disk bug */
  338. X        len = strlen(name);
  339. X        pos = pos - len - 1;
  340. X        newlock = ParentDir(mylock);
  341. X        UnLock(mylock);
  342. X        mylock = newlock;
  343. X        strncpy(path + pos, name, len);
  344. X        if (mylock)
  345. X            path[pos + len] = '/';
  346. X        else
  347. X            path[pos + len] = ':';
  348. X    } while (mylock);
  349. X    p->pr_WindowPtr = oldwin;    /* Enable error requesters again */
  350. X
  351. X    if (err) {
  352. X        /*
  353. X         *        Volume not present so have to be happy with just
  354. X         *        returning the volume node instead.
  355. X         */
  356. X        struct FileLock *fl = BTOC(lock);
  357. X        struct DeviceList *dl = BTOC(fl->fl_Volume);
  358. X        UBYTE *name = BTOC(dl->dl_Name);
  359. X
  360. X        strncpy(path, name + 1, *name);
  361. X        path[*name] = '\0';
  362. X        strcat(path, ":.../");
  363. X        return (path);
  364. X    } else
  365. X        return (path + pos);
  366. X}
  367. X
  368. X/*
  369. X *        makepath()
  370. X *        ----------
  371. X *        Builds a full path string given a process ptr and a filename.
  372. X *        If the filename includes relative references (// or :)
  373. X *        these are handled also. The point of this is to resolve relative
  374. X *        directory references.
  375. X *
  376. X *        Returns TRUE if a new string was generated, FALSE if the existing
  377. X *        string didn't depend on the current directory (this doesn't affect
  378. X *        the output stored in buf though).
  379. X */
  380. Xint makepath(char *buf, BPTR curdir, char *filename)
  381. X{
  382. X    char *origfilename = filename;
  383. X    int pos;
  384. X    int doneroot = 0;
  385. X
  386. X    /*
  387. X     *        Special check for the 'current process console' file '*'
  388. X     */
  389. X    if (strcmp(filename, "*") == 0) {
  390. X        strcpy(buf, filename);
  391. X        return (FALSE);
  392. X    }
  393. X
  394. X    strcpy(buf, getlockpath(curdir));
  395. X    pos = strlen(buf);
  396. X
  397. X    for (;;) {
  398. X        if (!doneroot && *filename == ':') {
  399. X            /*
  400. X             *        Path is relative to root
  401. X             */
  402. X            doneroot = 1;
  403. X            for (pos = 0; buf[pos] && buf[pos] != ':'; pos++)
  404. X                ;
  405. X            if (buf[pos] == ':')
  406. X                pos++;
  407. X        } else if (*filename == '/') {
  408. X            /*
  409. X             *        Path is relative to parent directory; if none, then
  410. X             *        remains the same.
  411. X             */
  412. X            int newpos = pos - 2;
  413. X            while (newpos >= 0 && buf[newpos] != '/' && buf[newpos] != ':')
  414. X                newpos--;
  415. X            if (newpos >= 0)
  416. X                pos = newpos + 1;
  417. X        } else {
  418. X            /*
  419. X             *        No more special characters; just append what's left of
  420. X             *        the filename.
  421. X             */
  422. X            if (!doneroot) {
  423. X                /*
  424. X                 *        If the filename wasn't relative to the root
  425. X                 *        directory, then make sure there are no device/volume
  426. X                 *        references contained within it. We copy the original
  427. X                 *        filename rather than the currently modified version
  428. X                 *        since a volume name of /A: is legal and the / would
  429. X                 *        be stripped off the modified name.
  430. X                 */
  431. X                char *p;
  432. X                for (p = filename; *p; p++) {
  433. X                    if (*p == ':') {
  434. X                        strcpy(buf, origfilename);
  435. X                        return (0);
  436. X                    }
  437. X                }
  438. X            }
  439. X            strcpy(buf + pos, filename);
  440. X            return (1);
  441. X        }
  442. X        filename++;
  443. X    }
  444. X}
  445. X
  446. X/*
  447. X *        OutputLine()
  448. X *        ------------
  449. X *        Outputs a line of text in the main window, according to the
  450. X *        truncation mechanism used.
  451. X */
  452. X
  453. X/*
  454. X *        mainloop()
  455. X *        ----------
  456. X *        This is the main event loop for SnoopDOS, where everything happens.
  457. X *        Control is passed here when SnoopDOS first starts up. When this
  458. X *        function returns, it terminates the background process.
  459. X */
  460. Xvoid mainloop(void)
  461. X{
  462. X    static char fullname[300];
  463. X    int done   = 0;                    /* True if finished processing            */
  464. X    int col0   = 1;                    /* True if cursor in column 0            */
  465. X    int nested = 0;                    /* True if nested DOS calls                */
  466. X
  467. X#define MISSED_NONE        0            /* Haven't missed anything    */
  468. X#define MISSED_OPEN        (1 << 0)    /* Missed Open() call        */
  469. X#define MISSED_LOCK        (1 << 1)    /* Missed Lock() call        */
  470. X#define MISSED_LOADSEG    (1 << 2)    /* Missed LoadSeg() call    */
  471. X#define MISSED_EXECUTE    (1 << 3)    /* Missed Execute() call    */
  472. X#define MISSED_CURDIR    (1 << 4)    /* Missed CurrentDir() call    */
  473. X#define MISSED_DELETE    (1 << 5)    /* Missed DeleteFile() call    */
  474. X
  475. X    int missed = MISSED_NONE;        /* Was a DOS function missed? See above    */
  476. X
  477. X    inport = CreatePort(PORTNAME, 0);
  478. X    if (!inport) {
  479. X        fprintf(stderr, "SnoopDos: Can't allocate message port.\n");
  480. X        cleanup(-1);
  481. X        return;
  482. X    }
  483. X
  484. X    myport  = inport;
  485. X    portsig = 1 << myport->mp_SigBit;
  486. X
  487. X    /*
  488. X     *        Allocate signals
  489. X     */
  490. X    missed_open_sig       = 1 << AllocSignal(-1);
  491. X    missed_lock_sig       = 1 << AllocSignal(-1);
  492. X    missed_loadseg_sig = 1 << AllocSignal(-1);
  493. X    missed_execute_sig = 1 << AllocSignal(-1);
  494. X    missed_curdir_sig  = 1 << AllocSignal(-1);
  495. X    missed_delete_sig  = 1 << AllocSignal(-1);
  496. X
  497. X    if (    missed_open_sig    == -1  || missed_lock_sig    == -1  ||
  498. X            missed_loadseg_sig == -1  || missed_execute_sig == -1  ||
  499. X            missed_curdir_sig  == -1  || missed_delete_sig  == -1) {
  500. X        fprintf(stderr, "SnoopDos: Can't allocate enough signals.\n");
  501. X        cleanup(-1);
  502. X        return;
  503. X    }
  504. X
  505. X    if (extfile) {
  506. X        debugwin = Open(extfilename, MODE_NEWFILE);
  507. X        if (!debugwin) {
  508. X            fprintf(stderr, "SnoopDos: Can't open file %s for output.\n",
  509. X                                extfilename);
  510. X            cleanup(-1);
  511. X            return;
  512. X        }
  513. X        fprintf(debugwin, "\r\n" TITLE "\r\n\r\n");
  514. X    } else {
  515. X        debugwin = Open(DEFWINDOW TITLE, MODE_NEWFILE);
  516. X        if (!debugwin) {
  517. X            fprintf(stderr, "SnoopDos: Can't open display window.\n");
  518. X            cleanup(-1);
  519. X            return;
  520. X        }
  521. X    }
  522. X    Close(stderr); stderr = NULL;
  523. X
  524. X    if (!extfile) {
  525. X        fprintf(debugwin, "\n"
  526. X    "Type CTRL-E/CTRL-D to enable/disable snooping. Type CTRL-C to exit.\n\n");
  527. X    };
  528. X    fprintf(debugwin, HEADER);
  529. X
  530. X    InitSemaphore(sem);
  531. X    snooptask = FindTask(0L);
  532. X    installdospatch();
  533. X
  534. X    /*
  535. X     *        Now just sit processing messages
  536. X     */
  537. X    while (!done) {
  538. X        int mask;
  539. X
  540. X#define SIGMASK    (portsig | missed_open_sig | missed_lock_sig | \
  541. X                 missed_loadseg_sig | missed_execute_sig |     \
  542. X                 missed_curdir_sig | missed_delete_sig |       \
  543. X                 SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E)
  544. X
  545. X        mask = Wait(SIGMASK);
  546. X
  547. X        if (mask & SIGBREAKF_CTRL_C)
  548. X            done = 1;
  549. X
  550. X        if (mask & SIGBREAKF_CTRL_D) {
  551. X            if (snoopactive) {
  552. X                fprintf(debugwin,
  553. X"\nSnooping now disabled; type CTRL-E to enable it again.\r\n\r\n");
  554. X                snoopactive = 0;
  555. X            }
  556. X        }
  557. X
  558. X        if (mask & SIGBREAKF_CTRL_E) {
  559. X            if (!snoopactive) {
  560. X                fprintf(debugwin,
  561. X"Snooping now enabled; type CTRL-D to disable it again.\r\n\r\n%s", HEADER);
  562. X                snoopactive = 1;
  563. X            }
  564. X        }
  565. X
  566. X        if (mask & missed_open_sig)
  567. X            missed |= MISSED_OPEN;
  568. X
  569. X        if (mask & missed_lock_sig)
  570. X            missed |= MISSED_LOCK;
  571. X
  572. X        if (mask & missed_loadseg_sig)
  573. X            missed |= MISSED_LOADSEG;
  574. X
  575. X        if (mask & missed_execute_sig)
  576. X            missed |= MISSED_EXECUTE;
  577. X
  578. X        if (mask & missed_curdir_sig)
  579. X            missed |= MISSED_CURDIR;
  580. X
  581. X        if (mask & missed_delete_sig)
  582. X            missed |= MISSED_DELETE;
  583. X
  584. X        if (mask & portsig) {
  585. X            MYMSG *msg;
  586. X
  587. X            /*
  588. X             *        Note in the following, there is some slightly tricky
  589. X             *        stuff to handle the case where a DOS function calls
  590. X             *        another DOS function internally. Under 1.3, this doesn't
  591. X             *        happen, but it may under WB 2.0 and in addition, Jim
  592. X             *        Goodnow's handy Rez utility patches LoadSeg() so that
  593. X             *        it calls Open(). `nested' is true when a nested call
  594. X             *        like this happens, and in this case, process names are
  595. X             *        printed out prefixed by `> ' to indicate the nesting.
  596. X             *
  597. X             *        The nesting is detected because an incoming Open/Lock/
  598. X             *        LoadSeg message will arrive when the cursor is positioned
  599. X             *        to print a Fail/Okay result from a previous call (i.e.
  600. X             *        col0 is false; the cursor is not in column 0). When a
  601. X             *        result arrives in and the cursor IS in column 0, then
  602. X             *        this must be the result from an earlier call so the
  603. X             *        nesting is ended. Note that the semaphores used ensures
  604. X             *        that this situation can only ever occur as a result of
  605. X             *        nesting; other tasks will always wait until they are
  606. X             *        properly in sync before sending messages to the main
  607. X             *        Snoopdos process.
  608. X             *
  609. X             *        The more alert among you are probably saying something
  610. X             *        like "Ah, but what if SnoopDos is configured to display
  611. X             *        all DOS calls, even if it means forcing some tasks to
  612. X             *        sleep until SnoopDos can process them? Then, when a
  613. X             *        task calls LoadSeg() (say) and LoadSeg() calls Open(),
  614. X             *        Open() will sleep forever waiting for the semaphore
  615. X             *        Obtain()ed by LoadSeg() to become free again." Well,
  616. X             *        in fact, it won't, since exec's ObtainSemaphore() call
  617. X             *        will suceed even when the semaphore is in use, IF the
  618. X             *        caller is the task that owns the semaphore -- and in such
  619. X             *        a case, the caller will be the same task. (It took me a
  620. X             *        while to figure out exactly what things were working --
  621. X             *        it looked like I should get a serious lockup in certain
  622. X             *        circumstances).
  623. X             *        
  624. X             */
  625. X            while ((msg = (MYMSG *)GetMsg(myport)) != NULL) {
  626. X                /*
  627. X                 *        Get the name of the process/command for
  628. X                 *        printing out if necessary.
  629. X                 */
  630. X                static char namebuf[256];
  631. X                UBYTE *procname = msg->process->pr_Task.tc_Node.ln_Name;
  632. X                struct CommandLineInterface *cli = BTOC(msg->process->pr_CLI);
  633. X                BPTR curdir = msg->process->pr_CurrentDir;
  634. X                UBYTE *s;
  635. X                UBYTE *filename;
  636. X                int newname;    /* If true, a new name was generated */
  637. X
  638. X                if (!col0 && (msg->msgtype == MSG_OPEN        ||
  639. X                              msg->msgtype == MSG_LOCK        ||
  640. X                              msg->msgtype == MSG_LOADSEG    ||
  641. X                              msg->msgtype == MSG_CURDIR    ||
  642. X                              msg->msgtype == MSG_DELETE)) {
  643. X                    nested = 1;
  644. X                    fprintf(debugwin, TXT_NEST);
  645. X                }
  646. X                if (cli && cli->cli_Module) {
  647. X                    UBYTE *cliname = BTOC(cli->cli_CommandName);
  648. X                    if (*cliname > 0) {
  649. X                        /* Only use CLI name if it's not null */
  650. X                        strncpy(namebuf+2, cliname + 1, *cliname);
  651. X                        namebuf[*cliname+2] = '\0';
  652. X                        procname = namebuf + 2;
  653. X                        if (nested) {
  654. X                            /*
  655. X                             *        If we're not at column 0, then we're
  656. X                             *        calling this DOS function from within
  657. X                             *        another DOS function so indent display
  658. X                             */
  659. X                            procname = namebuf;
  660. X                            procname[0] = '>';
  661. X                            procname[1] = ' ';
  662. X                        }
  663. X                    }
  664. X                } else {
  665. X                    if (nested) {
  666. X                        sprintf(namebuf, "> %s", procname);
  667. X                        procname = namebuf;
  668. X                    }
  669. X                }
  670. X
  671. X                /*
  672. X                 *        Now handle the message
  673. X                 */
  674. X                filename = msg->data2;    /* Standard file name            */
  675. X                newname  = 0;            /* No problems expanding it        */
  676. X
  677. X                switch (msg->msgtype) {
  678. X
  679. X                    case MSG_QUIT:
  680. X                        done = 1;
  681. X                        break;
  682. X
  683. X                    case MSG_GETOPTIONS:
  684. X                        memcpy(msg->data2, &settings, sizeof(SETTINGS));
  685. X                        break;
  686. X
  687. X                    case MSG_SETOPTIONS:
  688. X                        memcpy(&settings, msg->data2, sizeof(SETTINGS));
  689. X                        break;
  690. X
  691. X                    case MSG_OPEN:
  692. X                        if (msg->data1 == MODE_OLDFILE)
  693. X                            s = TXT_OLD;
  694. X                        else if (msg->data1 == MODE_NEWFILE)
  695. X                            s = TXT_NEW;
  696. X                        else if (msg->data1 == MODE_READWRITE)
  697. X                            s = TXT_R_W;
  698. X                        else
  699. X                            s = TXT_QM3;
  700. X
  701. X                        if (showfullpath) {
  702. X                            newname = makepath(fullname, curdir, msg->data2);
  703. X                            filename = fullname;
  704. X                        }
  705. X                        fprintf(debugwin, "%-21s %s %s%-39s %s ", procname,
  706. X                                    TXT_OPEN, POINT(newname), filename, s);
  707. X                        col0 = 0;
  708. X                        break;  
  709. X
  710. X                    case MSG_LOCK:
  711. X                        if (msg->data1 == ACCESS_READ)
  712. X                            s = TXT_SHAR;
  713. X                        else if (msg->data1 == ACCESS_WRITE)
  714. X                            s = TXT_EXCL;
  715. X                        else
  716. X                            s = TXT_QM4;
  717. X
  718. X                        if (showfullpath) {
  719. X                            newname = makepath(fullname, curdir, msg->data2);
  720. X                            filename = fullname;
  721. X                        }
  722. X                        fprintf(debugwin, "%-21s %s %s%-39s %s ", procname,
  723. X                                    TXT_LOCK, POINT(newname), filename, s);
  724. X                        col0 = 0;
  725. X                        break;
  726. X
  727. X                    case MSG_LOADSEG:
  728. X                        if (showfullpath) {
  729. X                            newname = makepath(fullname, curdir, msg->data2);
  730. X                            filename = fullname;
  731. X                        }
  732. X                        fprintf(debugwin, "%-21s %s %s%-44s ", procname,
  733. X                                    TXT_LOAD, POINT(newname), filename);
  734. X                        col0 = 0;
  735. X                        break;
  736. X
  737. X                    case MSG_EXECUTE:
  738. X                        fprintf(debugwin, "%-21s %s  %s\r\n", procname,
  739. X                                                    TXT_EXEC, filename);
  740. X                        col0 = 1;
  741. X                        break;
  742. X
  743. X                    case MSG_CURDIR:
  744. X                        {
  745. X                            char *dirname = getlockpath(msg->data1);
  746. X                            int i = strlen(dirname);
  747. X
  748. X                            if (dirname[i-1] == '/')
  749. X                                dirname[i-1] = '\0';
  750. X                            fprintf(debugwin, "%-21s %s  %s\r\n", procname,
  751. X                                                    TXT_CURDIR, dirname);
  752. X                            col0 = 1;
  753. X                        }
  754. X                        break;
  755. X
  756. X                    case MSG_DELETE:
  757. X                        if (showfullpath) {
  758. X                            newname = makepath(fullname, curdir, msg->data2);
  759. X                            filename = fullname;
  760. X                        }
  761. X                        fprintf(debugwin, "%-21s %s %s%-44s ", procname,
  762. X                                    TXT_DELETE, POINT(newname), filename);
  763. X                        col0 = 0;
  764. X                        break;
  765. X
  766. X                    case MSG_LOCK_DONE:
  767. X                    case MSG_OPEN_DONE:
  768. X                    case MSG_LOADSEG_DONE:
  769. X                    case MSG_DELETE_DONE:
  770. X                        if (col0 && nested) {
  771. X                            fprintf(debugwin, "%-73s", TXT_DONE);
  772. X                            nested = 0;
  773. X                        }
  774. X                        if (msg->data1)
  775. X                            fprintf(debugwin, TXT_OKAY);
  776. X                        else
  777. X                            fprintf(debugwin, TXT_FAIL);
  778. X                        col0 = 1;
  779. X                        break;
  780. X                }
  781. X                ReplyMsg(msg);
  782. X            }
  783. X        }
  784. X
  785. X        /*
  786. X         *        Finally, check if we missed a DOS function. If we did,
  787. X         *        AND we are in column 0, print out an appropriate message.
  788. X         *        Otherwise, wait until next time. This stops the display
  789. X         *        getting messed up when waiting to print a 'Fail' or 'Okay'.
  790. X         */
  791. X        if (missed) {
  792. X            if (col0) {
  793. X                if (missed & MISSED_OPEN)
  794. X                    fprintf(debugwin, "%s an Open()\r\n", TXT_WARN);
  795. X                if (missed & MISSED_LOCK)
  796. X                    fprintf(debugwin, "%s a Lock()\r\n", TXT_WARN);
  797. X                if (missed & MISSED_LOADSEG)
  798. X                    fprintf(debugwin, "%s a LoadSeg()\r\n", TXT_WARN);
  799. X                if (missed & MISSED_EXECUTE)
  800. X                    fprintf(debugwin, "%s an Execute()\r\n", TXT_WARN);
  801. X                if (missed & MISSED_CURDIR)
  802. X                    fprintf(debugwin, "%s a CurrentDir()\r\n", TXT_WARN);
  803. X                if (missed & MISSED_DELETE)
  804. X                    fprintf(debugwin, "%s a DeleteFile()\r\n", TXT_WARN);
  805. X                missed = MISSED_NONE;
  806. X            }
  807. X        }
  808. X    }
  809. X
  810. X    /*
  811. X     *        Remove the port from the public ports list; this stops any
  812. X     *        SnoopDos processes started up elsewhere from trying to
  813. X     *        communicate with us (which may happen if this process can't
  814. X     *        exit immediately).
  815. X     */
  816. X    RemPort(myport);
  817. X    myport->mp_Node.ln_Name = NULL;
  818. X
  819. X    /*
  820. X     *        Now remove the dospatch, reply to all messages currently
  821. X     *        pending and cleanup.
  822. X     */
  823. X    if (!uninstalldospatch()) {
  824. X        /*
  825. X         *        Someone else has patched DOSbase so print a message for
  826. X         *        the user and keep trying every 5 seconds until we succeed.
  827. X         */
  828. X        int count = 0;
  829. X
  830. X        fprintf(debugwin,
  831. X"\r\n"
  832. X"Someone else has patched dos.library so I'll have to wait until they quit."
  833. X"\r\n");
  834. X        if (!extfile) {
  835. X            fprintf(debugwin, 
  836. X  "This window will close shortly though to stop it from annoying you.\r\n");
  837. X        }
  838. X
  839. X        do {
  840. X            Delay(250);    /* Wait 5 seconds */
  841. X            if (debugwin) {
  842. X                count++;
  843. X                if (count > 2) {
  844. X                    Close(debugwin);
  845. X                    debugwin = NULL;
  846. X                }
  847. X            }
  848. X        } while (!uninstalldospatch());
  849. X    }
  850. X
  851. X    if (debugwin)
  852. X        fprintf(debugwin, "\r\nSnoopDos terminated.\r\n");
  853. X
  854. X    /*
  855. X     *        To make sure there is no code still executing in our task
  856. X     *        before we exit, we allocate the semaphore used to ensure
  857. X     *        exclusive access to the code, then wait a small time to allow
  858. X     *        the other task a chance to execute the final instruction or two
  859. X     *        left in our code after it releases the semaphore. This is not
  860. X     *        foolproof :-( but it's better than nothing.
  861. X     */
  862. X    {
  863. X        MYMSG *msg;
  864. X        while (msg = (MYMSG *)GetMsg(myport))
  865. X            ReplyMsg(msg);
  866. X    }
  867. X    ObtainSemaphore(sem);
  868. X    Delay(10);        /* Wait 0.2 seconds */
  869. X    cleanup(-1);
  870. X}
  871. X
  872. X/*
  873. X *        main()
  874. X *        ------
  875. X *        Mainline. Parses the command line and, if necessary, kicks off the
  876. X *        background task to do the real work.
  877. X */
  878. Xvoid main(int argc, char **argv)
  879. X{
  880. X    int error  = 0;            /* True if error detected in cmd line    */
  881. X    int quit   = 0;            /* True if we want to quit                */
  882. X    int colsel = 0;            /* True if colour option was specified    */
  883. X
  884. X    /*
  885. X     *        See if we are already active elsewhere; if yes, then read in
  886. X     *        the default settings used by that process.
  887. X     */
  888. X
  889. X    myport = FindPort(PORTNAME);
  890. X    if (myport)
  891. X        sendmsg(MSG_GETOPTIONS, 0, &settings);
  892. X
  893. X    while (argc > 1 && argv[1][0] == '-') {
  894. X        int val;
  895. X
  896. X        /* Make -X == -x0 and -x == -x1 */
  897. X        if (argv[1][1] >= 'a' && argv[1][2] != '0')
  898. X            val = 1;
  899. X        else
  900. X            val = 0;
  901. X
  902. X        switch (tolower(argv[1][1])) {
  903. X
  904. X            case 'a': colour         = val;
  905. X                      colsel        = 1;   break;    /* Display ANSI colour    */
  906. X            case 'c': docurdir        = val; break;    /* Monitor CurrentDir() */
  907. X            case 'd': dodelete        = val; break;    /* Monitor DeleteFile()    */
  908. X            case 'f': showfullpath    = val; break;    /* Show full filepath    */
  909. X            case 'g': doloadseg        = val; break;    /* Monitor LoadSeg()    */
  910. X            case 'h': error            = 1;   break;    /* Just print help msg    */
  911. X            case 'l': dolock        = val; break;    /* Monitor Lock()        */
  912. X            case 'm': snoopactive    = val; break;    /* Actively monitoring    */
  913. X            case 'o': doopen        = val; break;    /* Monitor Open()        */
  914. X            case 'q': quit            = 1;   break;    /* Ask SnoopDos to quit */
  915. X            case 'r': error            = 2;   break;    /* Report settings        */
  916. X            case 'w': sleepwait        = val; break;    /* Wait when necessary    */
  917. X            case 'x': doexecute        = val; break;    /* Monitor Execute()    */
  918. X            case 'z':
  919. X                    if (argv[1][2]) {
  920. X                        strcpy(extfilename, &argv[1][2]);
  921. X                        extfile = 1;
  922. X                    } else {
  923. X                        argv++;
  924. X                        argc--;
  925. X                        if (argc > 1) {
  926. X                            strcpy(extfile, argv[1]);
  927. X                            extfile = 1;
  928. X                        }
  929. X                    }
  930. X                    if (!extfile) {
  931. X                        printf(
  932. X        "-z must be followed by a filename. Type SnoopDos -h for help.\n");
  933. X                        exit(5);
  934. X                    }
  935. X                    /*
  936. X                     *        If outputting to a file, make colour off
  937. X                     *        by default, rather than on.
  938. X                     */
  939. X                    if (colsel == 0)
  940. X                        colour = 0;
  941. X                    break;
  942. X
  943. X            default:
  944. X                printf("Unrecognised option %s. Type Snoopdos -h for help.\n",
  945. X                                                                    argv[1]);
  946. X                exit(5);
  947. X        }
  948. X        argv++; argc--;
  949. X    }
  950. X
  951. X    if (argc > 1)
  952. X        error = 1;
  953. X
  954. X    if (error) {
  955. X        if (error == 1) {
  956. X            printf(TITLE "\n\n"
  957. X"SnoopDos monitors calls made to various AmigaDOS functions by all processes\n"
  958. X"on the system. The following options are available. Use -x1 or just -x to\n"
  959. X"enable an option, -X or -x0 to disable that option. Current settings in (-)."
  960. X"\n\n");
  961. X        } else
  962. X            printf("Current SnoopDos settings:\n\n");
  963. X
  964. X#define O(x,y) printf(x, y ? "(on)" : "(off)")
  965. XO("    -a  Use ANSI colour sequences                     %s\n", colour);
  966. XO("    -c  Monitor CurrentDir() calls                    %s\n", docurdir);
  967. XO("    -d  Monitor DeleteFile() calls                    %s\n", dodelete);
  968. XO("    -f  Display full filename paths                   %s\n", showfullpath);
  969. XO("    -g  Monitor LoadSeg() calls                       %s\n", doloadseg);
  970. XO("    -l  Monitor Lock() calls                          %s\n", dolock);
  971. XO("    -m  Globally enable/disable monitoring            %s\n", snoopactive);
  972. XO("    -o  Monitor Open() calls                          %s\n", doopen);
  973. XO("    -w  Display all activity, sleeping if necessary   %s\n", sleepwait);
  974. XO("    -x  Monitor Execute() calls                       %s\n", doexecute);
  975. X
  976. X        if (error == 1) {
  977. X            printf("\n"
  978. X"    -h  Print out this help message\n"
  979. X"    -q  Tell SnoopDos to quit\n"
  980. X"    -r  Report current SnoopDos settings\n" 
  981. X"    -z% Output to file % (e.g. -zCON:0/0/640/100/SnoopDos or -zSER:)\n"
  982. X"\n");
  983. X        }
  984. X        cleanup(5);
  985. X    }
  986. X
  987. X    /*
  988. X     *        First see are we already installed. If so, send a copy of the
  989. X     *        updated settings to the background process, or send a QUIT
  990. X     *        message if the user wanted to quit.
  991. X     */
  992. X    if (myport) {
  993. X        if (quit)
  994. X            sendmsg(MSG_QUIT, 0, 0);
  995. X        else
  996. X            sendmsg(MSG_SETOPTIONS, 0, &settings);
  997. X        cleanup(0);
  998. X    }
  999. X
  1000. X    /*
  1001. X     *        If user wanted to quit and we weren't already running, just
  1002. X     *        quit without doing anything.
  1003. X     */
  1004. X    if (quit) {
  1005. X        printf("There is no background SnoopDos process to tell to quit!\n");
  1006. X        cleanup(0);
  1007. X    }
  1008. X
  1009. X    /*
  1010. X     *        Not installed, so install ourselves. First of all though, we
  1011. X     *        kick ourselves into the background and return control to the
  1012. X     *        calling CLI. We need to do this before we start creating ports
  1013. X     *        and opening files, to prevent Exec and AmigaDOS getting
  1014. X     *        confused about which task we are.
  1015. X     *
  1016. X     *        Also open stderr channel for the new task to output fatal
  1017. X     *        error messages to; the new task takes responsibility for closing
  1018. X     *        this channel.
  1019. X     */
  1020. X    stderr = Open("*", MODE_NEWFILE);
  1021. X    if (!res("SnoopDos", 5, mainloop, 4000)) {
  1022. X        printf("Couldn't spawn background SnoopDos task.\n");
  1023. X        cleanup(10);
  1024. X    }
  1025. X}
  1026. X
  1027. X/*
  1028. X *        NewOpen()
  1029. X *        ---------
  1030. X *        This is the new Open() code. It checks to see if the calling task
  1031. X *        is actually the SnoopDos task; if it is, then it essentially does
  1032. X *        nothing (this stops any possible deadlock occurring). Otherwise,
  1033. X *        it sends a message to the task with the pertinent info.
  1034. X *
  1035. X *        If sleeping is disabled then if the semaphore isn't immediately
  1036. X *        available, a signal is sent to the Snoopdos task telling it that
  1037. X *        it's missed trapping a function.
  1038. X */
  1039. X__asm BPTR NewOpen(reg_d1 char *filename, reg_d2 int mode)
  1040. X{
  1041. X    BPTR filehandle;
  1042. X    geta4();
  1043. X    if (snoopactive && doopen && FindTask(0) != snooptask) {
  1044. X        if (sleepwait)
  1045. X            ObtainSemaphore(sem);
  1046. X        else if (!AttemptSemaphore(sem)) {
  1047. X            Signal(snooptask, missed_open_sig);
  1048. X            return (CallOpen(filename, mode));
  1049. X        }
  1050. X        sendmsg(MSG_OPEN, mode, filename);
  1051. X        filehandle = CallOpen(filename, mode);
  1052. X        sendmsg(MSG_OPEN_DONE, filehandle, 0);
  1053. X        ReleaseSemaphore(sem);
  1054. X        return (filehandle);
  1055. X    } else {
  1056. X        return (CallOpen(filename, mode));
  1057. X    }
  1058. X}
  1059. X/*
  1060. X *        NewLock()
  1061. X *        ---------
  1062. X *        Replacement for Lock(), all the comments for NewOpen() apply
  1063. X *        equally here.
  1064. X */
  1065. X__asm BPTR NewLock(reg_d1 char *filename, reg_d2 int mode)
  1066. X{
  1067. X    BPTR lock;
  1068. X    geta4();
  1069. X    if (snoopactive && dolock && FindTask(0) != snooptask) {
  1070. X        if (sleepwait)
  1071. X            ObtainSemaphore(sem);
  1072. X        else if (!AttemptSemaphore(sem)) {
  1073. X            Signal(snooptask, missed_lock_sig);
  1074. X            return (CallLock(filename, mode));
  1075. X        }
  1076. X        sendmsg(MSG_LOCK, mode, filename);
  1077. X        lock = CallLock(filename, mode);
  1078. X        sendmsg(MSG_LOCK_DONE, lock, 0);
  1079. X        ReleaseSemaphore(sem);
  1080. X        return (lock);
  1081. X    } else {
  1082. X        return (CallLock(filename, mode));
  1083. X    }
  1084. X}
  1085. X
  1086. X/*
  1087. X *        NewLoadSeg()
  1088. X *        ------------
  1089. X *        Replacement for Lock(), all the comments for NewOpen() apply
  1090. X *        equally here.
  1091. X */
  1092. X__asm BPTR NewLoadSeg(reg_d1 char *filename)
  1093. X{
  1094. X    BPTR seglist;
  1095. X    geta4();
  1096. X    if (snoopactive && doloadseg && FindTask(0) != snooptask) {
  1097. X        if (sleepwait)
  1098. X            ObtainSemaphore(sem);
  1099. X        else if (!AttemptSemaphore(sem)) {
  1100. X            Signal(snooptask, missed_loadseg_sig);
  1101. X            return (CallLoadSeg(filename));
  1102. X        }
  1103. X        sendmsg(MSG_LOADSEG, 0, filename);
  1104. X        seglist = CallLoadSeg(filename);
  1105. X        sendmsg(MSG_LOADSEG_DONE, seglist, 0);
  1106. X        ReleaseSemaphore(sem);
  1107. X        return (seglist);
  1108. X    } else {
  1109. X        return (CallLoadSeg(filename));
  1110. X    }
  1111. X}
  1112. X
  1113. X/*
  1114. X *        NewExecute()
  1115. X *        ------------
  1116. X *        Replacement for Execute()
  1117. X */
  1118. X__asm LONG NewExecute(reg_d1 char *command, reg_d2 BPTR in, reg_d3 BPTR out)
  1119. X{
  1120. X    geta4();
  1121. X    if (snoopactive && doexecute && FindTask(0) != snooptask) {
  1122. X        if (sleepwait)
  1123. X            ObtainSemaphore(sem);
  1124. X        else if (!AttemptSemaphore(sem)) {
  1125. X            Signal(snooptask, missed_execute_sig);
  1126. X            return(CallExecute(command, in, out));
  1127. X        }
  1128. X        sendmsg(MSG_EXECUTE, 0, command);
  1129. X        ReleaseSemaphore(sem);
  1130. X    }
  1131. X    return(CallExecute(command, in, out));
  1132. X}
  1133. X
  1134. X/*
  1135. X *        NewCurrentDir()
  1136. X *        ---------------
  1137. X *        Replacement for CurrentDir()
  1138. X */
  1139. X__asm BPTR NewCurrentDir(reg_d1 BPTR newlock)
  1140. X{
  1141. X    geta4();
  1142. X    if (snoopactive && docurdir && FindTask(0) != snooptask) {
  1143. X        if (sleepwait)
  1144. X            ObtainSemaphore(sem);
  1145. X        else if (!AttemptSemaphore(sem)) {
  1146. X            Signal(snooptask, missed_curdir_sig);
  1147. X            return(CallCurrentDir(newlock));
  1148. X        }
  1149. X        sendmsg(MSG_CURDIR, newlock, 0);
  1150. X        ReleaseSemaphore(sem);
  1151. X    }
  1152. X    return(CallCurrentDir(newlock));
  1153. X}
  1154. X
  1155. X/*
  1156. X *        NewDeleteFile()
  1157. X *        ---------------
  1158. X *        Replacement for DeleteFile()
  1159. X */
  1160. X__asm LONG NewDeleteFile(reg_d1 char *filename)
  1161. X{
  1162. X    LONG success;
  1163. X    geta4();
  1164. X    if (snoopactive && dodelete && FindTask(0) != snooptask) {
  1165. X        if (sleepwait)
  1166. X            ObtainSemaphore(sem);
  1167. X        else if (!AttemptSemaphore(sem)) {
  1168. X            Signal(snooptask, missed_delete_sig);
  1169. X            return(CallDeleteFile(filename));
  1170. X        }
  1171. X        sendmsg(MSG_DELETE, 0, filename);
  1172. X        success = CallDeleteFile(filename);
  1173. X        sendmsg(MSG_DELETE_DONE, success, 0);
  1174. X        ReleaseSemaphore(sem);
  1175. X    } else
  1176. X        return(CallDeleteFile(filename));
  1177. X}
  1178. END_OF_FILE
  1179. if test 32250 -ne `wc -c <'snoopdos.c'`; then
  1180.     echo shar: \"'snoopdos.c'\" unpacked with wrong size!
  1181. fi
  1182. # end of 'snoopdos.c'
  1183. fi
  1184. echo shar: End of archive 2 \(of 2\).
  1185. cp /dev/null ark2isdone
  1186. MISSING=""
  1187. for I in 1 2 ; do
  1188.     if test ! -f ark${I}isdone ; then
  1189.     MISSING="${MISSING} ${I}"
  1190.     fi
  1191. done
  1192. if test "${MISSING}" = "" ; then
  1193.     echo You have unpacked both archives.
  1194.     rm -f ark[1-9]isdone
  1195. else
  1196.     echo You still need to unpack the following archives:
  1197.     echo "        " ${MISSING}
  1198. fi
  1199. ##  End of shell archive.
  1200. exit 0
  1201. -- 
  1202. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1203. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1204. Post requests for sources, and general discussion to comp.sys.amiga.
  1205.